//-----------------------------------------------------
// logicfacade.h
//-----------------------------------------------------

/**
 * @file logicfacade.h
 * Contains the interface that must be implemented by the classes used
 * as communication facades between the logic and the Application/GUI
 *
 * @see logic::ILogicFacade
 *
 */

#pragma once

#include <vector>
#include <list>
#include <string>

namespace logic {

/**
 * Given that this class is pure game logic it must support various kinds of observers
 * The CreationDestructionObserver notifies the creation and destruction of game entities.
 * The GameEventsObserver is meant to notify important events in the development of the game
 * <p>
 * Internally the class is little more than an object container. During the game initialization
 * the map and the entities are created, and then they are updated periodically.
 * <p>
 * This update is done because the game recives from the application periodic invocations to
 * it's update() method. The update is distributed through the various game entities. Those entities
 * are who detect the important events in a global level (i.e player caught by enemy).
 * The entities that discover this kind of events notify them to the game they belong using one of
 * the eventXXXX methods. The game takes note of this important events, and notify them to it's observers
 * when all the logic update is finished.
 * <p>
 * The eventXXXX methods are public, but they are only for the logic entities interest, so they shouldn't
 * be invoked by other classes. By convenience is done this way instead of making them protected and making
 * friend all the interested classes.
 * <p>
 * On the other hand apart form the "ticks" for it's update, the game also recives from the outside the
 * actions the player wants to do. The way those are obtained depends on the application and is of no interest
 * here.
 * <p>
 * It must be mentioned the way they are recived. An enum ILogicFacade::TCommand exists to encapsulate the
 * information that externally we want to be able to send to the game regarding the movement of the player.
 * The commands are anotated internally and processated all at the same time as the initial step during the
 * game update in the update() method. The insertion of new commands is done through insertCommand().
 * <p>
 * This is a bit tangled. In essence the application detects that the user wants to do something. For this
 * it analyses the input, and sends a command to the game. The game takes note, and in the next update it
 * notifies the logic entity asociated with the player.
 * <p>
 * This entity analyses it's state, and infers the result. If there is something worth notifying, it sends an
 * event to the game, who, again, takes note. When it has the opportunity, the game checks if there are events
 * pending, if there are, spreads them to it's observers, where in some way resides the user interface.
 * This entangled process makes the network implementation easy, decoupling the moment the invocation is done
 * and the moment the result is recived, without freezing the application in any moment.
 *
 * @see logic::CGameObserver
 */

	class ILogicFacade {

		class CreationDestructionObserver;
		class GameEventsObserver;

	protected:

		std::list<CreationDestructionObserver*> creatDestrObservers;
		std::list<GameEventsObserver*> gameeventsObservers;

		bool playing;	// are we currently playing?

		// Constructor
		ILogicFacade();

	public:

		// Destructor
		virtual ~ILogicFacade();

		/******************************************/
		/*		TYPES PUBLISHED BY THE CLASS      */
		/******************************************/

		class CreationDestructionObserver {

		public:

			//virtual void staticEntityCreated(const ILogicFacade *facade, CStaticEntity *staticEntity) = 0;

			// TODO: notify the entity destruction?

		}; // CreationDestructionObserver

		class GameEventsObserver {


		}; // GameEventsObserver

		enum ECommandID {

			MOVEFWD,
			MOVEBWD,

		}; // enum ECommandID

		/**
		 * Data type for the commands that can be sent to the logic facade from the user interface.
		 * The command is the translated version of the user input, once processed and treated for it's
		 * handling by the game. This way we make the logic independent from the type of input, the key
		 * binding...
		 * The type of command is given by one of the fields. Depending on that field the rest of the fields
		 * could or could not have a relevant meaning.
		 *
		 * @note Currently a digital input is assumed. When the player wants to move his character, this
		 * movement is not adjusted by a movement speed: the player wants the character to move or stop.
		 * This limits the input for analog devices like joysticks.
		 */

		struct TCommand {

			ECommandID id;

			// In case of a movement command this field tells if the command must be initiated or stopped
			bool activate;

			int player;

			// Constructor by convenience
			TCommand(ECommandID cid, bool act = true, int i = 1) : id(cid), activate(act), player(i) {}

		}; // TCommand

		/*****************************************/
		/*		METHODS FOR THE APPLICATION      */
		/*****************************************/

		/**
		 * Init the logic
		 *
		 * @return false if the init failed
		 *
		 * @note Usually we want to register at least the CreationDestructionObserver before the invocation
		 * of this method, so the notification of the game entities is received.
		 */
		virtual bool init() = 0;

		// End the game. The subclasses will specialize it's behavior
		virtual void end() {}

		// Logic update tick
		virtual void update() = 0;

		// Insert a new logic command. It will be processed in the next update() call
		virtual void insertCommand(TCommand command) = 0;

		/*******************************/
		/*		OBSERVER METHODS       */
		/*******************************/

		// Add a new observer of the player related events
		//virtual bool addObserver(CPlayer::Observer* newObserver);

		// Remove a player related events observer
		//virtual bool removeObserver(CPlayer::Observer* oldObserver)

		// Add a new logic entities creation/destruction observer
		virtual bool addObserver(CreationDestructionObserver* newObserver);

		// Remove a logic entities creation/destruction observer
		virtual bool removeObserver(CreationDestructionObserver* oldObserver);

		// Add a new game events observer
		virtual bool addObserver(GameEventsObserver* newObserver);

		// Remove a game events observer
		virtual bool removeObserver(GameEventsObserver* oldObserver);

		/*****************************************************/
		/*		METHODS TO INVOKE THE FACADE OBSERVERS       */
		/*****************************************************/

		// An static entity has been created. Notify the GUIManager to create the graphic model
		//void emitStaticEntityCreated(CStaticEntity *staticEntity);

	}; // ILogicFacade

} // namespace logic